"""
安全API路由
提供安全审计、限流配置和安全统计功能
"""
from typing import Dict, Any, List, Optional
from datetime import datetime, timedelta
from fastapi import APIRouter, Depends, HTTPException, status, Request
from sqlalchemy.orm import Session
from pydantic import BaseModel, Field

from core.database import get_db
from core.auth import get_current_user, require_admin
from models.user import User
from services.security_service import (
    SecurityAuditor, RateLimiter, SecurityEventType, 
    ThreatLevel, get_security_statistics, log_security_event
)

# 创建路由器
security_router = APIRouter(prefix="/api/security", tags=["安全"])


class SecurityEventResponse(BaseModel):
    """安全事件响应模型"""
    id: int
    event_type: str
    user_id: Optional[int]
    username: Optional[str]
    ip_address: str
    endpoint: str
    method: str
    threat_level: str
    timestamp: datetime
    details: Dict[str, Any]


class RateLimitConfig(BaseModel):
    """限流配置模型"""
    endpoint: str = Field(..., description="端点路径")
    requests: int = Field(..., ge=10, description="请求数量限制")
    window: int = Field(..., ge=1, description="时间窗口（秒）")


class SecurityStatsResponse(BaseModel):
    """安全统计响应模型"""
    total_events: int
    events_by_type: Dict[str, int]
    events_by_threat_level: Dict[str, int]
    blocked_ips: int
    rate_limit_violations: int
    failed_login_attempts: int
    suspicious_requests: int
    period: str


class IPBlockRequest(BaseModel):
    """IP封锁请求模型"""
    ip_address: str = Field(..., description="IP地址")
    reason: str = Field(..., description="封锁原因")
    duration_hours: int = Field(24, ge=1, le=168, description="封锁时长（小时）")


@security_router.get("/statistics", response_model=SecurityStatsResponse)
async def get_security_stats(
    request: Request,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取安全统计信息"""
    # 记录访问事件
    await log_security_event(
        SecurityEventType.API_ACCESS,
        request,
        {"action": "get_security_statistics"},
        current_user.id,
        current_user.username
    )
    
    stats = await get_security_statistics()
    return SecurityStatsResponse(**stats)


@security_router.get("/events")
async def get_security_events(
    request: Request,
    event_type: Optional[str] = None,
    threat_level: Optional[str] = None,
    start_date: Optional[datetime] = None,
    end_date: Optional[datetime] = None,
    page: int = 1,
    page_size: int = 20,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取安全事件列表"""
    # 记录访问事件
    await log_security_event(
        SecurityEventType.API_ACCESS,
        request,
        {"action": "get_security_events", "filters": {
            "event_type": event_type,
            "threat_level": threat_level
        }},
        current_user.id,
        current_user.username
    )
    
    try:
        # 这里应该从数据库或日志文件读取安全事件
        # 为了演示，返回示例数据
        events = []
        
        # 构建查询条件
        filters = {}
        if event_type:
            filters["event_type"] = event_type
        if threat_level:
            filters["threat_level"] = threat_level
        if start_date:
            filters["start_date"] = start_date
        if end_date:
            filters["end_date"] = end_date
        
        # 返回分页数据
        return {
            "code": 200,
            "message": "success",
            "data": {
                "events": events,
                "total": len(events),
                "page": page,
                "page_size": page_size,
                "total_pages": (len(events) + page_size - 1) // page_size
            }
        }
        
    except Exception as e:
        await log_security_event(
            SecurityEventType.SUSPICIOUS_REQUEST,
            request,
            {"action": "get_security_events", "error": str(e)},
            current_user.id,
            current_user.username,
            ThreatLevel.MEDIUM
        )
        
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取安全事件失败: {str(e)}"
        )


@security_router.get("/rate-limits")
async def get_rate_limits(
    request: Request,
    current_user: User = Depends(require_admin),
    db: Session = Depends(get_db)
):
    """获取限流配置"""
    await log_security_event(
        SecurityEventType.API_ACCESS,
        request,
        {"action": "get_rate_limits"},
        current_user.id,
        current_user.username
    )
    
    try:
        # 获取限流器配置
        rate_limiter = RateLimiter()
        return {
            "code": 200,
            "message": "success",
            "data": {
                "limits": rate_limiter.limits,
                "ip_whitelist": list(rate_limiter.ip_whitelist),
                "user_limits": rate_limiter.user_limits
            }
        }
        
    except Exception as e:
        await log_security_event(
            SecurityEventType.SUSPICIOUS_REQUEST,
            request,
            {"action": "get_rate_limits", "error": str(e)},
            current_user.id,
            current_user.username,
            ThreatLevel.MEDIUM
        )
        
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取限流配置失败: {str(e)}"
        )


@security_router.post("/rate-limits")
async def update_rate_limit(
    config: RateLimitConfig,
    request: Request,
    current_user: User = Depends(require_admin),
    db: Session = Depends(get_db)
):
    """更新限流配置"""
    await log_security_event(
        SecurityEventType.SYSTEM_CONFIG_CHANGE,
        request,
        {"action": "update_rate_limit", "config": config.dict()},
        current_user.id,
        current_user.username
    )
    
    try:
        # 更新限流配置
        rate_limiter = RateLimiter()
        
        # 根据端点类型更新配置
        if config.endpoint.startswith("/api/auth"):
            rate_limiter.limits["auth"] = {"requests": config.requests, "window": config.window}
        elif config.endpoint.startswith("/api/upload"):
            rate_limiter.limits["upload"] = {"requests": config.requests, "window": config.window}
        elif config.endpoint.startswith("/api/"):
            rate_limiter.limits["api"] = {"requests": config.requests, "window": config.window}
        else:
            rate_limiter.limits["default"] = {"requests": config.requests, "window": config.window}
        
        return {
            "code": 200,
            "message": "限流配置更新成功",
            "data": config.dict()
        }
        
    except Exception as e:
        await log_security_event(
            SecurityEventType.SUSPICIOUS_REQUEST,
            request,
            {"action": "update_rate_limit", "error": str(e)},
            current_user.id,
            current_user.username,
            ThreatLevel.MEDIUM
        )
        
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"更新限流配置失败: {str(e)}"
        )


@security_router.post("/block-ip")
async def block_ip_address(
    block_request: IPBlockRequest,
    request: Request,
    current_user: User = Depends(require_admin),
    db: Session = Depends(get_db)
):
    """封锁IP地址"""
    await log_security_event(
        SecurityEventType.SYSTEM_CONFIG_CHANGE,
        request,
        {"action": "block_ip", "ip": block_request.ip_address, "reason": block_request.reason},
        current_user.id,
        current_user.username
    )
    
    try:
        security_auditor = SecurityAuditor()
        security_auditor.blocked_ips.add(block_request.ip_address)
        
        # 记录封锁事件
        await log_security_event(
            SecurityEventType.SUSPICIOUS_REQUEST,
            request,
            {
                "action": "ip_blocked",
                "ip": block_request.ip_address,
                "reason": block_request.reason,
                "duration": block_request.duration_hours
            },
            current_user.id,
            current_user.username,
            ThreatLevel.HIGH
        )
        
        return {
            "code": 200,
            "message": f"IP地址 {block_request.ip_address} 已被封锁",
            "data": {
                "ip_address": block_request.ip_address,
                "reason": block_request.reason,
                "duration_hours": block_request.duration_hours
            }
        }
        
    except Exception as e:
        await log_security_event(
            SecurityEventType.SUSPICIOUS_REQUEST,
            request,
            {"action": "block_ip", "error": str(e)},
            current_user.id,
            current_user.username,
            ThreatLevel.MEDIUM
        )
        
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"封锁IP地址失败: {str(e)}"
        )


@security_router.delete("/block-ip/{ip_address}")
async def unblock_ip_address(
    ip_address: str,
    request: Request,
    current_user: User = Depends(require_admin),
    db: Session = Depends(get_db)
):
    """解除IP封锁"""
    await log_security_event(
        SecurityEventType.SYSTEM_CONFIG_CHANGE,
        request,
        {"action": "unblock_ip", "ip": ip_address},
        current_user.id,
        current_user.username
    )
    
    try:
        security_auditor = SecurityAuditor()
        if ip_address in security_auditor.blocked_ips:
            security_auditor.blocked_ips.remove(ip_address)
            
            return {
                "code": 200,
                "message": f"IP地址 {ip_address} 已解除封锁",
                "data": {"ip_address": ip_address}
            }
        else:
            return {
                "code": 404,
                "message": f"IP地址 {ip_address} 未被封销",
                "data": None
            }
        
    except Exception as e:
        await log_security_event(
            SecurityEventType.SUSPICIOUS_REQUEST,
            request,
            {"action": "unblock_ip", "error": str(e)},
            current_user.id,
            current_user.username,
            ThreatLevel.MEDIUM
        )
        
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"解除IP封锁失败: {str(e)}"
        )


@security_router.get("/blocked-ips")
async def get_blocked_ips(
    request: Request,
    current_user: User = Depends(require_admin),
    db: Session = Depends(get_db)
):
    """获取被封锁的IP列表"""
    await log_security_event(
        SecurityEventType.API_ACCESS,
        request,
        {"action": "get_blocked_ips"},
        current_user.id,
        current_user.username
    )
    
    try:
        security_auditor = SecurityAuditor()
        blocked_ips = list(security_auditor.blocked_ips)
        
        return {
            "code": 200,
            "message": "success",
            "data": {
                "blocked_ips": blocked_ips,
                "count": len(blocked_ips)
            }
        }
        
    except Exception as e:
        await log_security_event(
            SecurityEventType.SUSPICIOUS_REQUEST,
            request,
            {"action": "get_blocked_ips", "error": str(e)},
            current_user.id,
            current_user.username,
            ThreatLevel.MEDIUM
        )
        
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取封锁IP列表失败: {str(e)}"
        )


@security_router.get("/threat-rules")
async def get_threat_rules(
    request: Request,
    current_user: User = Depends(require_admin),
    db: Session = Depends(get_db)
):
    """获取威胁检测规则"""
    await log_security_event(
        SecurityEventType.API_ACCESS,
        request,
        {"action": "get_threat_rules"},
        current_user.id,
        current_user.username
    )
    
    try:
        security_auditor = SecurityAuditor()
        rules = security_auditor.threat_detection_rules
        
        return {
            "code": 200,
            "message": "success",
            "data": {
                "rules": rules,
                "suspicious_patterns": security_auditor.suspicious_patterns
            }
        }
        
    except Exception as e:
        await log_security_event(
            SecurityEventType.SUSPICIOUS_REQUEST,
            request,
            {"action": "get_threat_rules", "error": str(e)},
            current_user.id,
            current_user.username,
            ThreatLevel.MEDIUM
        )
        
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取威胁检测规则失败: {str(e)}"
        )


@security_router.post("/clear-logs")
async def clear_security_logs(
    request: Request,
    days_to_keep: int = 30,
    current_user: User = Depends(require_admin),
    db: Session = Depends(get_db)
):
    """清理安全日志"""
    await log_security_event(
        SecurityEventType.SYSTEM_CONFIG_CHANGE,
        request,
        {"action": "clear_security_logs", "days_to_keep": days_to_keep},
        current_user.id,
        current_user.username
    )
    
    try:
        # 这里应该实现日志清理逻辑
        # 为了演示，返回成功响应
        
        return {
            "code": 200,
            "message": f"安全日志清理完成，保留最近 {days_to_keep} 天的日志",
            "data": {"days_to_keep": days_to_keep}
        }
        
    except Exception as e:
        await log_security_event(
            SecurityEventType.SUSPICIOUS_REQUEST,
            request,
            {"action": "clear_security_logs", "error": str(e)},
            current_user.id,
            current_user.username,
            ThreatLevel.MEDIUM
        )
        
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"清理安全日志失败: {str(e)}"
        )


@security_router.get("/dashboard")
async def get_security_dashboard(
    request: Request,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取安全仪表板数据"""
    await log_security_event(
        SecurityEventType.API_ACCESS,
        request,
        {"action": "get_security_dashboard"},
        current_user.id,
        current_user.username
    )
    
    try:
        # 获取各种统计数据
        security_auditor = SecurityAuditor()
        stats = await get_security_statistics()
        
        # 计算实时威胁指标
        real_time_metrics = {
            "active_threats": 0,
            "blocked_ips_today": 0,
            "failed_logins_today": 0,
            "suspicious_requests_today": 0
        }
        
        return {
            "code": 200,
            "message": "success",
            "data": {
                "statistics": stats,
                "real_time_metrics": real_time_metrics,
                "system_status": "secure",
                "last_updated": datetime.now()
            }
        }
        
    except Exception as e:
        await log_security_event(
            SecurityEventType.SUSPICIOUS_REQUEST,
            request,
            {"action": "get_security_dashboard", "error": str(e)},
            current_user.id,
            current_user.username,
            ThreatLevel.MEDIUM
        )
        
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取安全仪表板数据失败: {str(e)}"
        )